package com.licode.utils.unilite.utils;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.Objects;

/**
 * 网络接口工具类,用于获取ip地址，mac地址
 *
 * @author licode
 */
public class NetworkUtil {

    /**
     * 获取site-local的网络接口信息
     */
    public static String getLocalMac() throws UnknownHostException, SocketException {
        return getMacByInetAddress(getLocalHostLanAddress());
    }

    public static String getMacByInetAddress(InetAddress ia) throws SocketException {
        byte[] mac = NetworkInterface.getByInetAddress(ia).getHardwareAddress();
        if (Objects.isNull(mac)) {
            return "127.0.0.1";
        }

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < mac.length; i++) {
            if (i != 0) {
                sb.append('-');
            }
            int temp = mac[i] & 0xff;
            String str = Integer.toHexString(temp);
            if (str.length() == 1) {
                sb.append('0').append(str);
            } else {
                sb.append(str);
            }
        }
        return sb.toString().toUpperCase();
    }

    /**
     * 获取本机ip 尽量获取site-local
     */
    public static InetAddress getLocalHostLanAddress() throws UnknownHostException {
        try {
            InetAddress candidateAddress = null;

            // 遍历所有的网络接口
            for (Enumeration<NetworkInterface> netFaces = NetworkInterface.getNetworkInterfaces(); netFaces.hasMoreElements(); ) {
                NetworkInterface netFace = netFaces.nextElement();
                for (Enumeration<InetAddress> address = netFace.getInetAddresses(); address.hasMoreElements(); ) {
                    InetAddress inetAddr = (InetAddress) address.nextElement();
                    if (!inetAddr.isLoopbackAddress()) {
                        if (inetAddr.isSiteLocalAddress()) {
                            return inetAddr;
                        } else if (candidateAddress == null) {
                            candidateAddress = inetAddr;
                        }
                    }
                }
            }

            if (candidateAddress != null) {
                return candidateAddress;
            }

            InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
            if (jdkSuppliedAddress == null) {
                throw new UnknownHostException("The JDK InetAddress.getLocalHost() method unexpectedly returned null.");
            }

            return jdkSuppliedAddress;
        } catch (Exception e) {
            UnknownHostException unknownHostException = new UnknownHostException(
                    "Failed to determine LAN address: " + e);
            unknownHostException.initCause(e);
            throw unknownHostException;
        }
    }
}

